package github.sf.fw.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import github.sf.fw.utils.StrUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 序列化配置
 *
 * @author zhoup
 */
@Configuration
public class JacksonConfig {
    public static ObjectMapper sysDefaultConfig(ObjectMapper objectMapper) {
        // 全局配置序列化返回 JSON 处理
        SimpleModule simpleModule = new SimpleModule();
        //JSON Long ==> String
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        //使用Jackson序列化Gson的JsonObject
        simpleModule.addSerializer(JsonObject.class, new JsonSerializer<JsonObject>() {
            @Override
            public void serialize(JsonObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                if (value == null) {
                    gen.writeRawValue("{}");
                } else {
                    Gson gson = new GsonBuilder().serializeNulls().create();
                    gen.writeRawValue(gson.toJson(value));
                }
            }
        });
        //格式化时间
        String timeFormat = "yyyy-MM-dd HH:mm:ss";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(timeFormat);
        simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
        simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
        simpleModule.addSerializer(Date.class, new DateSerializer(null, new SimpleDateFormat(timeFormat)));
        //将时间解析为Date类型的方式
        simpleModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
            @Override
            public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                String text = jsonParser.getText();
                if (StrUtil.isEmpty(text)) {
                    return null;
                }
                LocalDateTime localDateTime = LocalDateTime.parse(text, dateTimeFormatter);
                ZoneId zoneId = ZoneId.systemDefault();
                //时区的日期和时间
                ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
                //获取时刻
                Instant instant = zonedDateTime.toInstant();
                return Date.from(instant);
            }
        });
        simpleModule.addDeserializer(JsonObject.class, new JsonDeserializer<JsonObject>() {
            @Override
            public JsonObject deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                String text = jsonParser.getText();
                if (StrUtil.isEmpty(text)) {
                    return null;
                }
                Gson gson = new GsonBuilder().serializeNulls().create();
                return gson.fromJson(text, JsonObject.class);
            }
        });
        //String的空字符串转为null
        simpleModule.addDeserializer(String.class, new JsonDeserializer<String>() {
            @Override
            public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                String text = jsonParser.getText();
                if (StrUtil.isEmpty(text)) {
                    return null;
                }
                return text;
            }
        });
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }

    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper = sysDefaultConfig(objectMapper);
        return objectMapper;
    }
}
